<template>
  <view class="role-auth">
    <view class="tree-view">
      <scroll-view class="tree-list" :scroll-y="true">
        <block v-for="(item, index) in treeList" :key="index">
          <view class="tree-item" :style="[{
    							paddingLeft: item.level*30 + 'rpx'
    						}]" :class="{
    							show: item.isShow
    						}">
            <view class="item-label">
              <view class="item-icon uni-inline-item" @tap.stop="_onItemSwitch(item, index)">
                <view v-if="!item.isLastLevel&&item.isShowChild" class="switch-on"
                  :style="{'border-left-color':switchColor}">
                </view>
                <view v-else-if="!item.isLastLevel&&!item.isShowChild" class="switch-off"
                  :style="{'border-top-color':switchColor}">
                </view>
                <view v-else class="item-last-dot" :style="{'border-top-color':switchColor}">
                </view>
              </view>
              <view class="flex flex-1  align-center" @tap.stop="_onItemSelect(item, index)">
                <view class="item-name flex align-center">
                  <view class="item-check" v-if="selectParent?true:item.isLastLevel">
                    <view class="item-check-yes status-1" v-if="item.checkStatus==1" :class="{'radio':!multiple}"
                      :style="{'border-color':primaryColor}">
                      <view class="item-check-yes-part" :style="{'background-color':primaryColor}">
                      </view>
                    </view>
                    <view class="item-check-yes" v-else-if="item.checkStatus==2" :class="{'radio':!multiple}"
                      :style="{'border-color':primaryColor}">
                      <view class="item-check-yes-all" :style="{'background-color':primaryColor}">
                      </view>
                    </view>
                    <view class="item-check-no" v-else :class="{'radio':!multiple}"
                      :style="{'border-color':primaryColor}"></view>
                  </view>
                  <text> {{item.name+(item.childCount?"("+item.childCount+")":'')}}</text>
                </view>

              </view>
            </view>

          </view>
        </block>
      </scroll-view>
    </view>
    <!-- </view> -->
  </view>
</template>

<script>
  /**
   * @description 角色权限树型列表
   * @property {String} roleNo 角色编号
   * @property {Boolean} unfold=[true|false] 全部展开/全部折叠 默认true全部展开
   * @property {Boolean} linkage=[true|false] 父子节点是否联动 即选中部分子节点后 父节点显示为半选中状态，选中全部子节点后 父节点显示为选中状态，取消选中所有子节点后 父节点为取消选中状态
   * @property {String} valueKey 唯一字段的key，默认为id
   * @property {String} textKey  显示字段的key，默认为name
   * @property {String} childrenKey  子数据的key，默认为children
   * @property {Array} localdata  扁平化的树型数据
   * @property {Array} localTreeList  树型数据
   * @property {Array} selectedData  默认选中的数据
   * @property {String} primaryColor  按钮的颜色
   * @property {String} switchColor  节点切换图标的颜色
   * @property {Boolear} multiple=[true|false]  是否可以多选
   * @event {Function()} select-change 节点数据改变事件 
   */
  export default {
    name: "role-authority",
    emits: ['select-change'],
    props: {
      roleNo: {
        type: String,
        default: ''
      },
      // 全部展开
      unfold: {
        type: Boolean,
        default: true
      },
      // 父子联动
      linkage: {
        type: Boolean,
        default: true
      },
      valueKey: {
        type: String,
        default: 'id'
      },
      textKey: {
        type: String,
        default: 'name'
      },
      childrenKey: {
        type: String,
        default: 'children'
      },
      localdata: {
        type: Array,
        default: function() {
          return []
        }
      },
      localTreeList: { //在已经格式化好的数据
        type: Array,
        default: function() {
          return []
        }
      },
      selectedData: {
        type: Array,
        default: function() {
          return []
        }
      },
      multiple: { // 是否可以多选
        type: Boolean,
        default: true
      },
      selectParent: { //是否可以选父级
        type: Boolean,
        default: true
      },
      primaryColor: { // 主颜色
        type: String,
        default: '' // #38C09E
      },
      switchColor: { // 节点切换图标颜色
        type: String,
        default: '' // #666
      }
    },
    data() {
      return {
        treeList: []
      }
    },
    methods: {
      _confirm() { //多选
        let selectedList = []; //如果子集全部选中，只返回父级 id
        let selectedNames;
        let currentLevel = -1;
        this.treeList.forEach((item, index) => {
          if (currentLevel >= 0 && item.level > currentLevel) {

          } else {
            if (item.checkStatus === 2) {
              currentLevel = item.level;
              selectedList.push(item.id);
              selectedNames = selectedNames ? selectedNames + ' / ' + item.name : item.name;
            } else {
              currentLevel = -1;
            }
          }
        })
        this.$emit("select-change", selectedList, selectedNames);
        return {
          selectedList,
          selectedNames
        }
      },
      
      //格式化原数据（原数据为tree结构）
      _formatTreeData(list=[],level=0,parentItem,parentIndex){
          let nextIndex = 0;
          let parentId = -1;
          let initCheckStatus = 0;
          if (parentItem) {
            nextIndex = this.treeList.findIndex(item => item.id === parentItem.id) + 1;
            parentId = parentItem.id;
            if (!this.multiple) { //单选
              initCheckStatus = 0;
            } else
              initCheckStatus = parentItem.checkStatus == 2 ? 2 : 0;
          }
          list.forEach(item => {
            let isLastLevel = true;
            if (item && item[this.childrenKey]) {
              let children = item[this.childrenKey];
              if (Array.isArray(children) && children.length > 0) {
                isLastLevel = false;
              }
            }
        
            let itemT = {
              id: item[this.valueKey],
              name: item[this.textKey],
              level,
              isLastLevel,
              isShow: true,
              isShowChild: true,
              checkStatus: initCheckStatus,
              orCheckStatus: 0,
              parentId,
              children: item[this.childrenKey],
              childCount: item[this.childrenKey] ? item[this.childrenKey].length : 0,
              childCheckCount: 0,
              childCheckPCount: 0
            };
        
            if (this.selectedData.indexOf(itemT.id) >= 0) {
              itemT.checkStatus = 2;
              itemT.orCheckStatus = 2;
              itemT.childCheckCount = itemT.children ? itemT.children.length : 0;
              this._onItemParentSelect(itemT, nextIndex);
            }
            let children = this.deepClone(itemT.children)
            itemT.children = undefined;
             
            this.treeList.splice(nextIndex, 0, itemT);
            nextIndex++;
            if (this.unfold && children) {
              if (Array.isArray(children) && children.length > 0) {
                this._formatTreeData(children, itemT.level + 1, itemT);
              }
            }
            nextIndex+=children.length;
          })
      },
      // 节点打开、关闭切换
      _onItemSwitch(item, index) {
        // console.log(item)
        //console.log('_itemSwitch')
        if (item.isLastLevel === true) {
          return;
        }
        item.isShowChild = !item.isShowChild;
        if (item.children) {
          this._formatTreeData(item.children, item.level + 1, item);
          item.children = undefined;
        } else {
          this._onItemChildSwitch(item, index);
        }
      },
      _onItemChildSwitch(item, index) {
        //console.log('_onItemChildSwitch')
        const firstChildIndex = index + 1;
        if (firstChildIndex > 0)
          for (var i = firstChildIndex; i < this.treeList.length; i++) {
            let itemChild = this.treeList[i];
            if (itemChild.level > item.level) {
              if (item.isShowChild) {
                if (itemChild.parentId === item.id) {
                  itemChild.isShow = item.isShowChild;
                  if (!itemChild.isShow) {
                    itemChild.isShowChild = false;
                  }
                }
              } else {
                itemChild.isShow = item.isShowChild;
                itemChild.isShowChild = false;
              }
            } else {
              return;
            }
          }
      },
      // 节点选中、取消选中
      _onItemSelect(item, index) {
        //console.log('_onItemSelect')
        //console.log(item)
        if (!this.multiple) { //单选
          item.checkStatus = item.checkStatus == 0 ? 2 : 0;

          this.treeList.forEach((v, i) => {
            if (i != index) {
              this.treeList[i].checkStatus = 0
            } else {
              this.treeList[i].checkStatus = 2
            }
          })

          let selectedList = [];
          let selectedNames;
          selectedList.push(item.id);
          selectedNames = item.name;
          this.$emit("select-change", selectedList, selectedNames);
          return
        }

        let oldCheckStatus = item.checkStatus;
        switch (oldCheckStatus) {
          case 0:
            item.checkStatus = 2;
            item.childCheckCount = item.childCount;
            item.childCheckPCount = 0;
            break;
          case 1:
          case 2:
            item.checkStatus = 0;
            item.childCheckCount = 0;
            item.childCheckPCount = 0;
            break;
          default:
            break;
        }
        //子节点 全部选中
        this._onItemChildSelect(item, index);
        //父节点 选中状态变化
        this._onItemParentSelect(item, index, oldCheckStatus);
      },
      _onItemChildSelect(item, index) {
        //console.log('_onItemChildSelect')
        let allChildCount = 0;
        if (item.childCount && item.childCount > 0) {
          index++;
          while (index < this.treeList.length && this.treeList[index].level > item.level) {
            let itemChild = this.treeList[index];
            itemChild.checkStatus = item.checkStatus;
            if (itemChild.checkStatus == 2) {
              itemChild.childCheckCount = itemChild.childCount;
              itemChild.childCheckPCount = 0;
            } else if (itemChild.checkStatus == 0) {
              itemChild.childCheckCount = 0;
              itemChild.childCheckPCount = 0;
            }
            // console.log('>>>>index：', index, 'item：', itemChild.name, '  status：', itemChild
            // 	.checkStatus)
            index++;
          }
        }
      },
      _onItemParentSelect(item, index, oldCheckStatus) {
        //console.log('_onItemParentSelect')
        //console.log(item)
        const parentIndex = this.treeList.findIndex(itemP => itemP.id == item.parentId);
        //console.log('parentIndex：' + parentIndex)
        if (parentIndex >= 0) {
          let itemParent = this.treeList[parentIndex];
          let count = itemParent.childCheckCount;
          let oldCheckStatusParent = itemParent.checkStatus;

          if (oldCheckStatus == 1) {
            itemParent.childCheckPCount -= 1;
          } else if (oldCheckStatus == 2) {
            itemParent.childCheckCount -= 1;
          }
          if (item.checkStatus == 1) {
            itemParent.childCheckPCount += 1;
          } else if (item.checkStatus == 2) {
            itemParent.childCheckCount += 1;
          }

          if (itemParent.childCheckCount <= 0 && itemParent.childCheckPCount <= 0) {
            itemParent.childCheckCount = 0;
            itemParent.childCheckPCount = 0;
            itemParent.checkStatus = 0;
          } else if (itemParent.childCheckCount >= itemParent.childCount) {
            itemParent.childCheckCount = itemParent.childCount;
            itemParent.childCheckPCount = 0;
            itemParent.checkStatus = 2;
          } else {
            itemParent.checkStatus = 1;
          }
          this._onItemParentSelect(itemParent, parentIndex, oldCheckStatusParent);
        }
      },
      // 重置数据
      _reTreeList() {
        this.treeList.forEach((v, i) => {
          this.treeList[i].checkStatus = v.orCheckStatus
        })
      },
      _initTree() {
        this.treeList = [];
        this._formatTreeData(this.localdata);
      }
    },
    watch: {
      localdata() {
        this._initTree();
      },
      localTreeList() {
        this.treeList = this.localTreeList;
      }
    },
    mounted() {
      this._initTree();
    }
  }
</script>

<style lang="scss" scoped>
  .role-auth {
    width: 100%;
    height: 100%;
  }

  .tree-list {
    flex: 1;
    height: 100%;
    overflow: hidden;
  }

  .tree-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    line-height: 1;
    height: 0;
    opacity: 0;
    transition: 0.2s;
    overflow: hidden;
    width: 100%;
  }

  .tree-item.show {
    height: 6rem;
    opacity: 1;
  }

  .tree-item.showchild:before {
    transform: rotate(90deg);
  }

  .tree-item.last:before {
    opacity: 0;
  }

  .switch-on {
    width: 0;
    height: 0;
    border-left: 1rem solid transparent;
    border-right: 1rem solid transparent;
    border-top: 1.4rem solid #666;
  }

  .switch-off {
    width: 0;
    height: 0;
    border-bottom: 1rem solid transparent;
    border-top: 1rem solid transparent;
    border-left: 1.4rem solid #666;
  }

  .item-last-dot {
    position: absolute;
    width: 1rem;
    height: 1rem;
    border-radius: 100%;
    background: #666;
  }

  .item-icon {
    width:2rem;
    height: 2rem;
    margin-right: 1rem;
    padding-right: 1rem;
    padding-left: 1rem;
  }

  .item-label {
    flex: 1;
    display: flex;
    align-items: center;
    height: 100%;
    line-height: 1.2;
    min-width: 20rem;
  }

  .item-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 2.4rem;
  }

  .item-check {
    width: 6rem;
    height: 6rem;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .item-check-yes,
  .item-check-no {
    width: 2.4rem;
    height: 2.4rem;
    border-top-left-radius: 20%;
    border-top-right-radius: 20%;
    border-bottom-right-radius: 20%;
    border-bottom-left-radius: 20%;
    border-top-width: 1rpx;
    border-left-width: 1rpx;
    border-bottom-width: 1rpx;
    border-right-width: 1rpx;
    border-style: solid;
    border-color: $retail-color-primary;
    display: flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
  }

  .item-check-yes {
    background-color: $retail-color-primary;
  }

  .item-check-yes-part {
    width: 1.6rem;
    height: 0.4rem;
    border-top-left-radius: 20%;
    border-top-right-radius: 20%;
    border-bottom-right-radius: 20%;
    border-bottom-left-radius: 20%;
    background-color: #fff;
    ;
  }

  .item-check-yes-all {
    margin-bottom: .5rem;
    border: 2px solid #fff;
    ;
    border-left: 0;
    border-top: 0;
    height: 1.6rem;
    width: 0.8rem;
    transform-origin: center;
    /* #ifndef APP-NVUE */
    transition: all 0.3s;
    /* #endif */
    transform: rotate(45deg);
  }

  .item-check .radio {
    border-top-left-radius: 50%;
    border-top-right-radius: 50%;
    border-bottom-right-radius: 50%;
    border-bottom-left-radius: 50%;
  }

  .item-check .radio .item-check-yes-b {
    border-top-left-radius: 50%;
    border-top-right-radius: 50%;
    border-bottom-right-radius: 50%;
    border-bottom-left-radius: 50%;
  }

  .hover-c {
    opacity: 0.6;
  }

  .itemBorder {
    border-bottom: 1px solid #e5e5e5;
  }
</style>
